package com.lei2j.dubbo.consumer;

import com.lei2j.dubbo.pojo.ValidateParams;
import com.lei2j.dubbo.service.DemoService;
import com.lei2j.dubbo.service.AsyncDubboService;
import com.lei2j.dubbo.service.DubboGenericService;
import com.lei2j.dubbo.service.ValidateService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.service.EchoService;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@SpringBootApplication
@RestController
public class DubboConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplication.class, args);
    }

    //分组“*”，选择任意一个分组调用
    @Reference(group = "group2",async = true,actives = 2,methods = {@Method(name = "say",onreturn = "notify" +
            ".onReturn",onthrow = "notify.onThrow")})
    private DemoService demoService;

    @Reference
    private ValidateService validateService;

    @Reference(generic = true)
    private DubboGenericService dubboGenericService;

    @Reference(async = true)
    private AsyncDubboService asyncDubboService;

    @RequestMapping("/test")
    public String get(String name){
        return demoService.say(name);
    }

    @RequestMapping("/validate-save")
    public ResponseEntity<ValidateParams> save(ValidateParams validateParams){
        return ResponseEntity.ok(validateService.save(validateParams));
    }
    @RequestMapping("/validate-update")
    public ResponseEntity<ValidateParams> update(ValidateParams validateParams){
        return ResponseEntity.ok(validateService.update(validateParams));
    }
    @RequestMapping("/validate-param")
    public ResponseEntity<ValidateParams> param(ValidateParams validateParams){
        return ResponseEntity.ok(validateService.validateObject(validateParams));
    }

    @RequestMapping("/validate-len")
    public ResponseEntity<String> len(int x){
        validateService.validateParam(x);
        URL url = RpcContext.getContext().getUrl();
        System.out.println(url);
        return ResponseEntity.ok("ok");
    }

    @RequestMapping("/generic")
    public ResponseEntity<String> generic(String name){
        GenericService genericService = (GenericService)dubboGenericService;
        String generic = dubboGenericService.generic(name);
//        Object invoke = ((GenericService) dubboGenericService).$invoke("generic", new String[]{"java.lang.String"}, new Object[]{name});
        return ResponseEntity.ok(generic);
    }

    @RequestMapping("/echo")
    public String echo(String name){
        EchoService echoService = (EchoService)demoService;
        return String.valueOf(echoService.$echo(name));
    }

    @RequestMapping("/attachment")
    public Object attach(String attach){
        RpcContext.getContext().setAttachment("attach",attach);
        return demoService.attach();
    }

   @RequestMapping("/async")
    public String async(String name) throws ExecutionException, InterruptedException {
        //方法1
//       CompletableFuture<String> completableFuture = asyncDubboService.async(name);
//       completableFuture.whenComplete((v,t)->{
//           if (t != null) {
//               t.printStackTrace();
//           } else {
//               System.out.println(v);
//           }
//       });
//       System.out.println("async out");
       CompletableFuture<String> future = RpcContext.getContext().asyncCall(() -> asyncDubboService.future(name));
//       String s = future.get();
       return null;
   }

   @RequestMapping("/concurrent")
    public String concurrent(String name){
       for (int i = 0; i < 10; i++) {
           final int x = i;
           new Thread(()-> System.out.println(x+":"+demoService.concurrent(name))).start();
       }
       return "ok";
   }
}
